import axios, { AxiosError, AxiosInstance } from 'axios';
import { ChainType } from '@/config/chains';
import { getApiBaseUrl, API_VERSION } from '@/config/api';
import { getAuthToken, removeAuthToken, setAuthToken, getRefreshToken } from './auth';
import toast from 'react-hot-toast';

// Multi-chain API client factory
export class MultiChainApiClient {
  private clients: Map<ChainType, AxiosInstance> = new Map();

  constructor() {
    this.initializeClients();
  }

  private initializeClients() {
    const chains: ChainType[] = ['mainnet', 'testnet'];
    
    chains.forEach(chain => {
      const client = axios.create({
        baseURL: getApiBaseUrl(chain),
        headers: {
          'Content-Type': 'application/json',
        },
      });

      // Request interceptor
      client.interceptors.request.use(
        (config) => {
          const token = getAuthToken(chain);
          if (token) {
            config.headers.Authorization = `Bearer ${token}`;
          }
          return config;
        },
        (error) => Promise.reject(error)
      );

      // Response interceptor
      client.interceptors.response.use(
        (response) => response,
        async (error: AxiosError) => {
          const originalRequest = error.config as any;
          
          if (error.response?.status === 401 && !originalRequest._retry) {
            originalRequest._retry = true;
            
            try {
              const refreshToken = getRefreshToken(chain);
              if (refreshToken) {
                const response = await axios.post(`${getApiBaseUrl(chain)}${API_VERSION}/auth/refresh`, {
                  refresh_token: refreshToken,
                });
                
                const { access_token } = response.data;
                setAuthToken(access_token, chain);
                
                originalRequest.headers.Authorization = `Bearer ${access_token}`;
                return client(originalRequest);
              }
            } catch (refreshError) {
              removeAuthToken(chain);
              // Don't redirect, let the app handle chain-specific auth
              // window.location.href = '/login';
            }
          }
          
          if (error.response?.status !== 401) {
            const message = (error.response?.data as any)?.detail || `API Error (${chain})`;
            toast.error(message);
          }
          
          return Promise.reject(error);
        }
      );

      this.clients.set(chain, client);
    });
  }

  // Get API client for specific chain
  getClient(chain: ChainType): AxiosInstance {
    const client = this.clients.get(chain);
    if (!client) {
      throw new Error(`API client not found for chain: ${chain}`);
    }
    return client;
  }

  // Make request to specific chain
  async request<T>(chain: ChainType, config: any): Promise<T> {
    const client = this.getClient(chain);
    const response = await client(config);
    return response.data;
  }

  // Make requests to all chains
  async requestAll<T>(config: any): Promise<Record<ChainType, T>> {
    const requests = Array.from(this.clients.entries()).map(async ([chain, client]) => {
      try {
        const response = await client(config);
        return { chain, data: response.data };
      } catch (error) {
        console.error(`Request failed for ${chain}:`, error);
        return { chain, data: null };
      }
    });

    const results = await Promise.all(requests);
    
    return results.reduce((acc, { chain, data }) => {
      acc[chain] = data;
      return acc;
    }, {} as Record<ChainType, T>);
  }

  // Health check for all chains
  async healthCheck(): Promise<Record<ChainType, boolean>> {
    try {
      const results = await this.requestAll<any>({
        method: 'GET',
        url: '/health',
      });

      return Object.entries(results).reduce((acc, [chain, data]) => {
        acc[chain as ChainType] = data?.status === 'healthy';
        return acc;
      }, {} as Record<ChainType, boolean>);
    } catch (error) {
      console.error('Health check failed:', error);
      return {
        mainnet: false,
        testnet: false,
      };
    }
  }
}

// Global instance
export const multiChainApi = new MultiChainApiClient();

// Legacy default export (backward compatibility)
export default multiChainApi.getClient('mainnet');